﻿using AVCUMPlatform.CORPWXService.Interface;
using AVCUMPlatform.HelperLibrary;
using AVCUMPlatform.CORPWXService.Model;
using System;
using System.Reflection.Metadata;
using Newtonsoft.Json;
using HelperLibrary;

namespace AVCUMPlatform.WXService.Service
{
    /// <summary>
    /// 微信接口访问工具类
    /// </summary>
    public class CorpWXService : ICorpWXPlatformApiHelper
    {
        /// <summary>
        /// appid
        /// </summary>
        private string _appid { get; set; }
        /// <summary>
        /// appSecret
        /// </summary>
        private string _appSecret { get; set; }
        /// <summary>
        /// 客户端地址
        /// </summary>
        private string _clientHost { get; set; }
        /// <summary>
        /// 企业应用的id
        /// </summary>
        private Int64 _agendId { get; set; }
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="appSecret"></param>
        /// <param name="clientHost"></param>
        /// <param name="agendId"></param>
        public CorpWXService(string appid, string appSecret, string clientHost, Int64 agendId)
        {
            _appid = appid;
            _appSecret = appSecret;
            _clientHost = clientHost;
            _agendId = agendId;
        }


        /// <summary>
        /// 发送取消预约消息
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="title">eg: 自习预约/场地预约</param>
        /// <param name="time">eg: 2020年12月23日 上午十点</param>
        /// <param name="siteName">eg: 泉山17号楼 101</param>
        /// <param name="reason">eg: 与课表安排冲突</param>
        /// <param name="bookingCancel"></param>
        /// <param name="orderId"></param>
        /// <param name="remark">eg: 谢谢您的理解与支持！</param>
        /// <returns></returns>
        public SendTemplateMsgRes SendCancelOrderMsg(string openId, string title,
            string time, string siteName, string reason, string bookingCancel,int orderId,string remark = "谢谢您的理解与支持!")
        {
            try
            {
                string value = string.Empty; 
                var url = string.Empty;
                if (string.IsNullOrEmpty(reason))
                {
                    value = $"您的{title}已被取消";
                }
                else
                {
                    value = $"您的{title}由于{reason}已被取消";
                }
                int type = 0;
                if (title == "场地预约")
                {
                    type = 0;
                    url = $"{_clientHost}/pages/approval/details?id={orderId}&type={type}&clienttype=2";
                }
                else if (title.Contains("调课"))
                {
                    type = 1;
                    url = $"{_clientHost}/pages/approval/details?id={orderId}&type={type}&clienttype=2";
                }
                else if (title == "停课")
                {
                    type = 2;
                    url = $"{_clientHost}/pages/approval/details?id={orderId}&type={type}&clienttype=2";
                }
                else if (title == "实验室预约")
                {
                    type = 4;
                    url = $"{_clientHost}/pages/approval/details?id={orderId}&type={type}&clienttype=2";
                }
                else if (title == "自习预约" || title == "座位预约")
                {
                    url = $"{_clientHost}/pages/myBook/details?id={orderId}&currtype=2";
                }
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = "预约取消提醒",
                        description = $"<div class=\"normal\">{value}</div>" +
                        $"<div class=\"normal\">预约项目：{title}(场地:{siteName})</div>" +
                        $"<div class=\"normal\">预约时间：{time}</div>" +
                        $"<div class=\"normal\">{remark}</div>",
                        url = url,
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送取消批量预约消息
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="title">eg: 自习预约/场地预约</param>
        /// <param name="project"></param>
        /// <param name="time">eg: 2020年12月23日 上午十点</param>
        /// <param name="siteName">eg: 泉山17号楼 101</param>
        /// <param name="reason">eg: 与课表安排冲突</param>
        /// <param name="bookingCancel"></param>
        /// <param name="batchOrderId"></param>
        /// <param name="remark">eg: 谢谢您的理解与支持！</param>
        /// <returns></returns>
        public SendTemplateMsgRes SendCancelBatchOrderMsg(string openId, string title, string project,
            string time, string siteName, string reason, string bookingCancel,int batchOrderId, string remark = "谢谢您的理解与支持!")
        {
            try
            {
                string value = string.Empty;
                if (string.IsNullOrEmpty(reason))
                {
                    value = $"您的{title}已被取消";
                }
                else
                {
                    value = $"您的{title}由于{reason}已被取消";
                }
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = "预约取消提醒",
                        description = $"<div class=\"normal\">{value}</div>" +
                        $"<div class=\"normal\">预约项目：{project}(场地:{siteName})</div>" +
                        $"<div class=\"normal\">预约时间：{time}</div>" +
                        $"<div class=\"normal\">{remark}</div>",
                        url = $"{_clientHost}/pages/approval/details?id={batchOrderId}&type=3&clienttype=2",
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送待审批提醒
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="orderId">预约id</param>
        /// <param name="applicantName">eg：张三</param>
        /// <param name="flowName">eg: 重要会议预约</param>
        /// <param name="content">eg: 场地：A01，使用时间：2019-12-23日第五节</param>
        /// <param name="applyTime">2020-12-23 12:23</param>
        /// <param name="auditRemind"></param>
        /// <returns></returns>
        public SendTemplateMsgRes SendAuditRemindMsg(string openId, int orderId,
            string applicantName, string flowName, string content, string applyTime, string auditRemind)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(content))
                {
                    content = content.Substring(0, 20) + "...";
                }
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = "审批提醒",
                        description = $"<div class=\"normal\">【{applicantName}】有一个新的场地订单需要您审批</div>" +
                        $"<div class=\"normal\">审批流程：{flowName}</div>" +
                        $"<div class=\"normal\">内容详情：{content}</div>" +
                        $"<div class=\"normal\">申请人：{applicantName}</div>" +
                        $"<div class=\"normal\">时间：{applyTime}</div>" +
                        $"<div class=\"normal\">请尽快处理</div>",
                        url = $"{_clientHost}/pages/approval/details?id={orderId}&type=0&clienttype=2",
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送批量待审批提醒
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="batchOrderId">预约id</param>
        /// <param name="applicantName">eg：张三</param>
        /// <param name="flowName">eg: 重要会议预约</param>
        /// <param name="content">eg: 场地：A01，使用时间：2019-12-23日第五节</param>
        /// <param name="applyTime">2020-12-23 12:23</param>
        /// <param name="auditRemind"></param>
        /// <returns></returns>
        public SendTemplateMsgRes SendBatchAuditRemindMsg(string openId, int batchOrderId,
            string applicantName, string flowName, string content, string applyTime, string auditRemind)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(content))
                {
                    content = content.Substring(0, 20) + "...";
                }
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = "审批提醒",
                        description = $"<div class=\"normal\">【{applicantName}】有一个新的批量订单需要您审批</div>" +
                        $"<div class=\"normal\">审批流程：{flowName}</div>" +
                        $"<div class=\"normal\">内容详情：{content}</div>" +
                        $"<div class=\"normal\">申请人：{applicantName}</div>" +
                        $"<div class=\"normal\">时间：{applyTime}</div>" +
                        $"<div class=\"normal\">请尽快处理</div>",
                        url = $"{_clientHost}/pages/approval/details?id={batchOrderId}&type=3&clienttype=2",
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }


        /// <summary>
        /// 发送待审批提醒
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="orderId"></param>
        /// <param name="applicantName"></param>
        /// <param name="flowName"></param>
        /// <param name="content"></param>
        /// <param name="applyTime"></param>
        /// <param name="auditName"></param>
        /// <param name="auditRemind"></param>
        /// <param name="type">1:调课2:停课</param>
        /// <returns></returns>
        public SendTemplateMsgRes SendAdjustAuditRemindMsg(string openId, int orderId,
            string applicantName, string flowName, string content, string applyTime, string auditName, string auditRemind, int type = 1)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(content))
                {
                    content = content.Substring(0, 20) + "...";
                }
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = "审批提醒",
                        description = $"<div class=\"normal\">【{applicantName}】有一个新的{auditName}订单需要您审批</div>" +
                        $"<div class=\"normal\">审批流程：{flowName}</div>" +
                        $"<div class=\"normal\">内容详情：{content}</div>" +
                        $"<div class=\"normal\">申请人：{applicantName}</div>" +
                        $"<div class=\"normal\">时间：{applyTime}</div>" +
                        $"<div class=\"normal\">请尽快处理</div>",
                        url = $"{_clientHost}/pages/approval/details?id={orderId}&type={type}&clienttype=2",
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 发送审批状态提醒
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="auditorName"></param>
        /// <param name="flowType">场地/自习</param>
        /// <param name="site">17号楼A101</param>
        /// <param name="time">第八周 星期四 第3节</param>
        /// <param name="res">审批通过/驳回</param>
        /// <param name="bookingReject"></param>
        /// <param name="bookingApprove"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public SendTemplateMsgRes SendBookingStatusMsg(string openId, string auditorName,
            string flowType, string site, string time, string res, string bookingReject, string bookingApprove,int orderId)
        {
            try
            {
                var title = "预约申请通过提醒";
                string template_id = bookingApprove;
                string firstValue = "您的订单已经审批通过！";
                if (res != "审批通过")
                {
                    template_id = bookingReject;
                    firstValue = $"您的订单被【{auditorName}】驳回！"; 
                    title = "预约审批驳回提醒";
                }
                int type = 0;
                if (flowType == "场地")
                {
                    type = 0;
                }
                else if (flowType == "调课")
                {
                    type = 1;
                }
                else if (flowType == "停课")
                {
                    type = 2;
                }
                else if (flowType.Contains("批量"))
                {
                    type = 3;
                }
                else if (flowType == "实验室")
                {
                    type = 4;
                }
                if (!string.IsNullOrWhiteSpace(time))
                {
                    time = time.Substring(0, 20) + "...";
                }
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = title,
                        description = $"<div class=\"normal\">{firstValue}</div>" +
                        $"<div class=\"normal\">审批项：{flowType}订单</div>" +
                        $"<div class=\"normal\">场地：{site}</div>" +
                        $"<div class=\"normal\">时间：{time}</div>" +
                        $"<div class=\"normal\">审批结果：{res}</div>" +
                        $"<div class=\"normal\">感谢您的使用</div>",
                        url = $"{_clientHost}/pages/approval/details?id={orderId}&type={type}&clienttype=2",
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }
        /// <summary>
        /// 发给场地管理员消息
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="flowType">场地/自习</param>
        /// <param name="site">17号楼A101</param>
        /// <param name="time">第八周 星期四 第3节</param>
        /// <param name="res">审批通过/驳回</param>
        /// <param name="orderId">订单id</param>
        /// <returns></returns>
        public SendTemplateMsgRes SendToSiteManagerRemind(string openId, string flowType, string site, string time, string res, int orderId) 
        {
            try
            {
                var bookingResult = "通过";
                string resStr = res;
                string flowTypeStr = flowType;
                if (res == "取消")
                {
                    resStr = "取消预约";
                    bookingResult = "取消";
                }
                int type = 0;
                if (flowType == "场地")
                {
                    type = 0;
                }
                else if (flowType == "调课")
                {
                    resStr = "取消调课";
                    flowTypeStr = "场地";
                    type = 1;
                }
                else if (flowType == "停课")
                {
                    resStr = "取消停课";
                    flowTypeStr = "场地";
                    type = 2;
                }
                else if (flowType.Contains("批量"))
                {
                    type = 3;
                    flowTypeStr = "场地";
                }
                else if (flowType == "实验室")
                {
                    type = 4;
                }
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = $"您管理的{flowTypeStr}[{site}]已被{resStr}",
                        description = $"<div class=\"normal\">时间：{time}</div>" +
                        $"<div class=\"normal\">地点：{site}</div>" +
                        $"<div class=\"normal\">预约结果：{bookingResult}</div>" +
                        $"<div class=\"normal\">请您合理安排时间，及时关注使用情况！</div>",
                        url = $"{_clientHost}/pages/approval/details?id={orderId}&type={type}&clienttype=2",
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }
        /// <summary>
        /// 发送通知
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="toUserName">eg: 张三</param>
        /// <param name="title">eg: 全校放假通知</param>
        /// <param name="datetime">2020-12-23 12:23</param>
        /// <param name="content">庆祝台湾解放，全校放假一天，请知晓</param>
        /// <param name="remark">谢谢合作！</param>
        /// <returns></returns>
        public SendTemplateMsgRes SendInform(string openId,
            string toUserName, string title, string datetime, string content)
        {
            try
            {
                CorpWXTemplateMsgRM msgRM = new CorpWXTemplateMsgRM
                {
                    touser = openId,
                    agentid = Convert.ToInt64(_agendId),
                    textcard = new DataModel
                    {
                        title = title,
                        description = $"<div class=\"gray\">{datetime}</div> <div class=\"normal\">{toUserName}, 您有一条新的通知</div><div class=\"highlight\">{content}</div><div class=\"highlight\">如有疑问，请联系预约管理员！</div>",
                        url = "",
                        btntxt = ""
                    }
                };
                return SendTemplateMsg(msgRM);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex);
                return null;
            }
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public CorpWXUserInfo GetUserInfo(string code)
        {
            string token = CorpWXToken.GetInstance(_appid, _appSecret).AccessToken;
            string url = $"https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token={token}&code={code}";
            CorpWXUserInfo corpWXUserInfo = HTTPHelper.Get<CorpWXUserInfo>(url);
            return corpWXUserInfo;
        }

        /// <summary>
        /// 发布菜单
        /// </summary>
        /// <param name="firstMenuName"></param>
        public CorpWXRes PublishMenu(string firstMenuName)
        {
            try
            {
                string token = CorpWXToken.GetInstance(_appid, _appSecret).AccessToken;
                string url = $"https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token={token}&agentid={_agendId}";
                List<CorpWXButton> buttons = GetMenu(firstMenuName, _clientHost);
                var param = new
                {
                    button = buttons
                };
                return HTTPHelper.Post<CorpWXRes>(url, param);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 获取微信菜单
        /// </summary>
        /// <returns></returns>
        private List<CorpWXButton> GetMenu(string firstMenuName,string hostUrl)
        {
            List<CorpWXButton> buttons = new List<CorpWXButton>();
            buttons.Add(new CorpWXButton
            {
                type = "view",
                name = firstMenuName,
                url = hostUrl,
                sub_button = new List<CorpWXButton>()
            });
            return buttons;
        }

        /// <summary>
        /// 发送模板消息
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public SendTemplateMsgRes SendTemplateMsg(CorpWXTemplateMsgRM data)
        {
            try
            {
                //Log.Write($"request:{JsonConvert.SerializeObject(data)}");
                string token = CorpWXToken.GetInstance(_appid, _appSecret).AccessToken;
                string url = $"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}";
                SendTemplateMsgRes sendTemplateMsgRes = HTTPHelper.Post<SendTemplateMsgRes>(url, data);
                if (sendTemplateMsgRes.msgid == null)
                {

                    token = CorpWXToken.GetInstance(_appid, _appSecret).RefreshToken();
                    url = $"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}";
                    sendTemplateMsgRes = HTTPHelper.Post<SendTemplateMsgRes>(url, data);
                }
                return sendTemplateMsgRes;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 发送普通消息
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public SendTemplateMsgRes SendNormalMsg(CorpWXNormalMsgRM data)
        {
            //Log.Write($"request:{JsonConvert.SerializeObject(data)}");
            string token = CorpWXToken.GetInstance(_appid, _appSecret).AccessToken;
            string url = $"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}";
            SendTemplateMsgRes sendMsgRes = HTTPHelper.Post<SendTemplateMsgRes>(url, data);
            if (sendMsgRes.msgid == null)
            {
                token = CorpWXToken.GetInstance(_appid, _appSecret).RefreshToken();
                url = $"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}";
                sendMsgRes = HTTPHelper.Post<SendTemplateMsgRes>(url, data);
            }
            return sendMsgRes;
        }

        /// <summary>
        /// 通过手机号发送普通消息
        /// </summary>
        /// <param name="userPhones">用户手机号（多个逗号隔开）</param>
        /// <param name="content">内容</param>
        /// <returns></returns>
        public SendTemplateMsgRes SendNormalMsgByPhones(string userPhones,string content)
        {
            try
            {
                CorpWXNormalMsgRM corpWXNormalMsgRM = new CorpWXNormalMsgRM
                {
                    agentid = _agendId,
                    msgtype = "text",
                    text = new TextDataModel { content = content },
                };
                if (!string.IsNullOrWhiteSpace(userPhones))
                {
                    corpWXNormalMsgRM.touser = GetUserId(userPhones);
                }

                return SendNormalMsg(corpWXNormalMsgRM);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public string GetUserId(string mobiles)
        {
            var userIdStr = string.Empty;
            string token = CorpWXToken.GetInstance(_appid, _appSecret).AccessToken;
            if (string.IsNullOrWhiteSpace(mobiles))
            {
                return string.Empty;
            }
            else
            {
                var mobileList = mobiles.Split(",").ToList();
                if (mobileList != null && mobileList.Any())
                {
                    var userIdList = new List<string>();
                    foreach (var mobile in mobileList)
                    {
                        var corpwx_userid = CacheHelper.Get<string>($"corpwx_userid_{mobile}");
                        if (!string.IsNullOrWhiteSpace(corpwx_userid))
                        {
                            userIdList.Add(corpwx_userid);
                        }
                        else
                        {
                            string url = $"https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token={token}";
                            UserIdByPhoneRes result = HTTPHelper.Post<UserIdByPhoneRes>(url,new { mobile });
                            if (result != null && !string.IsNullOrWhiteSpace(result.userid))
                            {
                                userIdList.Add(result.userid);
                                CacheHelper.Set($"corpwx_userid_{result.userid}", result.userid, TimeSpan.FromDays(30));
                            }
                        }
                    }
                    if (userIdList.Any())
                    {
                        userIdStr = string.Join("|", userIdList);
                    }
                }
            }

            return userIdStr;
        }
    }
}